﻿using System;
using System.ServiceModel;
using LayeredArchitectureSample.DomainModel;

namespace LayeredArchitectureSample.ViewModel
{
    // TODO: figure out the relation of this with service operation invoker. Can you use the Decorator here?
    internal class ExceptionAwareServiceCodeRunner : IExceptionAwareServiceCodeRunner
    {
        private readonly IUserInteractionService _userInteractionService;

        public ExceptionAwareServiceCodeRunner(IUserInteractionService userInteractionService)
        {
            if (userInteractionService == null) throw new ArgumentNullException("userInteractionService");

            _userInteractionService = userInteractionService;
        }

        public void RunCode(Action codeToRun)
        {
            if (codeToRun == null) throw new ArgumentNullException("codeToRun");

            try
            {
                codeToRun.Invoke();
            }
            catch (CannotAddEntityException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (ArgumentException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (CannotRemoveEntityException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (EntityNotFoundException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (EntityRetrievalException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (FailedToUpdateEntityException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (OperationFailedException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (CommunicationException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (TimeoutException exception)
            {
                _userInteractionService.DisplayErrorMessage(exception);
            }
            catch (Exception exception)
            {
                _userInteractionService.DisplayErrorMessageForUnknownErrorBeforeShutdown(exception);

                throw;
            }
        }
    }
}